package com.dongjiantong.web.boss.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.dongjiantong.common.exceptions.HttpCode;
import com.dongjiantong.common.exceptions.OPServerException;
import com.dongjiantong.common.model.Response;
import com.dongjiantong.common.utils.MD5Util;
import com.dongjiantong.common.utils.RandomUtil;
import com.dongjiantong.common.web.sso.LoginInfo;
import com.dongjiantong.common.web.util.UserUtil;
import com.dongjiantong.openplatform.annotations.OpenBean;
import com.dongjiantong.openplatform.annotations.OpenMethod;
import com.dongjiantong.sys.model.SysLabelModel;
import com.dongjiantong.user.enums.FarmsEnum;
import com.dongjiantong.user.enums.OrgTypeEnum;
import com.dongjiantong.user.enums.UserEnum;
import com.dongjiantong.user.model.*;
import com.dongjiantong.user.model.dtos.FarmsDto;
import com.dongjiantong.user.service.*;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMethod;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
 * Created by ThinkPad on 2017/12/25.
 */
@Slf4j
@OpenBean
public class UserController {

    @Reference(version = "1.0.0")
    private MzUserService mzUserService;
    @Reference(version = "1.0.0")
    private SSOLoginService ssoLoginService;
    @Reference(version = "1.0.0")
    private RoleAppUserService roleAppUserService;
    @Reference(version = "1.0.0")
    private OrganizationUserService organizationUserService;
    @Reference(version = "1.0.0")
    private OrgFramUserService orgFramUserService;
    @Reference(version = "1.0.0")
    private RegionAccountService regionAccountService;
    @Reference(version = "1.0.0")
    private OrganizationService organizationService;
    @Reference(version = "1.0.0")
    private OrgUserAreaService orgUserAreaService;
    @Reference(version = "1.0.0")
    private FarmsService farmsService;
    @Reference(version = "1.0.0")
    private LogsUserLoginService logsUserLoginService;

    @Reference(version = "1.0.0")
    private FarmsUserService farmsUserService;

    /**
     * @param mzUser          人员信息
     * @param roleAppUser     角色
     * @param orgUser         单位
     * @param depUser         部门
     * @param userAreaList    用户区域
     * @param declarationList 申报点（List数组）
     * @param certUserList    发证点（List数组）
     * @param orgButUser      管理屠宰场（List数组）
     * @param orgBreeUser     管理养殖场（List数组）
     * @param orgRetailUser   管理散养场 （List数组）
     * @return
     */
    @OpenMethod(key = "boss.user.createOrgUser",
            paramNames = {
                    "mzUser",
                    "roleAppUser",
                    "orgUser",
                    "depUser",
                    "userAreaList",
                    "declarationList",
                    "certUserList",
                    "orgButUser",
                    "orgBreeUser",
                    "orgRetailUser",
                    "password"},
            httpMethods = RequestMethod.POST)
    @Transactional
    public Response createGovUser(MzUser mzUser,
                                  RoleAppUser roleAppUser,
                                  OrganizationUser orgUser,
                                  OrganizationUser depUser,
                                  List<Map> userAreaList,
                                  List<Map> declarationList,
                                  List<Map> certUserList,
                                  List<Map> orgButUser,
                                  List<Map> orgBreeUser,
                                  List<Map> orgRetailUser,
                                  String password) {
        try {

            //人员详情
            mzUser.setUserType(UserEnum.USERTYPE_ORG.getCode());
            mzUser.setCreatedAt(new Date());
            mzUser.setRelationId(orgUser.getOrgId());//单位Id
            mzUser.setDeleteFlag(1);
            Long userID = mzUserService.insert(mzUser);
            //登录表
            LoginUser loginUser = new LoginUser();
            String salt = RandomUtil.generateLowerString(3);
            loginUser.setSalt(salt);
            loginUser.setPassword(MD5Util.encrypt(salt + password));
            loginUser.setErrorcount(0);
            loginUser.setLogincount(0);
            loginUser.setStatus(UserEnum.LOGIN_DISABLE.getCode());
            loginUser.setUserId(userID);
            loginUser.setUsername(mzUser.getMobile());
            loginUser.setUnlocktime(new Date());
            ssoLoginService.insert(loginUser);
            //创建角色
            roleAppUser.setStatus(1);
            roleAppUser.setUserId(userID);
            roleAppUser.setCreatedAt(new Date());
            roleAppUserService.insert(roleAppUser);
            //单位
            orgUser.setUserId(userID);
            orgUser.setType(OrgTypeEnum.OrgType_organization.getCode());
            organizationUserService.insert(orgUser);
            //部门
            depUser.setUserId(userID);
            depUser.setType(OrgTypeEnum.OrgType_department.getCode());
            organizationUserService.insert(depUser);


            //----------------------------------官方兽医----------------------------------------------------
            //管辖区域(list)
            if (userAreaList.size() != 0) {
                List<UserArea> list = new ArrayList<>();
                for (Map map : userAreaList) {
                    UserArea userArea = toBean(UserArea.class, map);
                    userArea.setUserId(userID);
                    list.add(userArea);
                }
                orgUserAreaService.insertList(list);
            }

            //todo 只有官方兽医才可以有 要判断
            // 申报点（数组list）
            if (declarationList.size() != 0) {
                List<OrganizationUser> list = new ArrayList<>();
                for (Map map : declarationList) {
                    OrganizationUser organizationUser = new OrganizationUser();
                    organizationUser.setOrgId(Long.valueOf(String.valueOf(map.get("orgId"))).longValue());
                    organizationUser.getOrgId();
                    organizationUser.setUserId(userID);
                    organizationUser.setType(OrgTypeEnum.OrgType_declaration.getCode());
                    list.add(organizationUser);
                }
                organizationUserService.insertList(list);
            }

            //出证点（数组list）
            if (certUserList.size() != 0) {
                List<OrganizationUser> list = new ArrayList<>();
                for (Map map : certUserList) {
                    OrganizationUser organizationUser = new OrganizationUser();
                    organizationUser.setOrgId(Long.valueOf(String.valueOf(map.get("orgId"))).longValue());
                    organizationUser.getOrgId();
                    organizationUser.setUserId(userID);
                    organizationUser.setType(OrgTypeEnum.OrgType_cert.getCode());
                    list.add(organizationUser);
                }
                organizationUserService.insertList(list);

            }


            //屠宰场
            if (orgButUser.size() != 0) {
                List<OrgFramsUser> list = new ArrayList<>();
                for (Map map : orgButUser) {
                    OrgFramsUser orgFramsUser = new OrgFramsUser();
                    orgFramsUser.setUserId(userID);
                    orgFramsUser.setFarmId(Long.valueOf(String.valueOf(map.get("farmId"))).longValue());
                    orgFramsUser.setType(FarmsEnum.Butcher.getCode());
                    list.add(orgFramsUser);
                }
                orgFramUserService.insertList(list);

            }

            //---------------------------协检员  管理员----------------------------
            if (orgBreeUser.size() != 0) {
                List<OrgFramsUser> list = new ArrayList<>();
                for (Map map : orgBreeUser) {
                    OrgFramsUser orgFramsUser = new OrgFramsUser();
                    orgFramsUser.setUserId(userID);
                    orgFramsUser.setFarmId(Long.valueOf(String.valueOf(map.get("farmId"))).longValue());
                    orgFramsUser.setType(FarmsEnum.Breed.getCode());
                    list.add(orgFramsUser);
                }
                orgFramUserService.insertList(list);
            }


            //------------------乡村防疫员
            if (orgRetailUser.size() != 0) {
                List<OrgFramsUser> list = new ArrayList<>();
                for (Map map : orgRetailUser) {
                    OrgFramsUser orgFramsUser = new OrgFramsUser();
                    orgFramsUser.setUserId(userID);
                    orgFramsUser.setFarmId(Long.valueOf(String.valueOf(map.get("farmId"))).longValue());
                    orgFramsUser.setType(FarmsEnum.Retail.getCode());
                    list.add(orgFramsUser);
                }
                orgFramUserService.insertList(list);
            }
            return Response.ok("创建成功");
        } catch (Exception e) {
            log.error(e.getMessage());
            e.printStackTrace();
            throw new OPServerException(HttpCode.DATA_CREATE_FAIL, "创建用户失败请稍后再试");
        }
    }


    /**
     * 根据单位查询申报点 和出证点
     *
     * @param orgId
     * @return
     */
    @OpenMethod(key = "boss.user.selectSiteByOrgID",
            paramNames = {"orgId"},
            httpMethods = RequestMethod.GET

    )
    public Response<Map> selectSiteByOrgID(Long orgId) {
        Organization organization = organizationService.selectByPrimaryKey(orgId);
        if (organization.getOrgType() == OrgTypeEnum.OrgType_organization.getCode()) {
            Organization organization1 = new Organization();
            organization1.setProvinceId(organization.getProvinceId());
            if (organization.getCityId() != 0) {
                organization1.setCityId(organization.getCityId());
                if (organization.getRegionId() != 0) {
                    organization1.setRegionId(organization.getRegionId());
                    if (organization.getStreetId() != 0) {
                        organization1.setStreetId(organization.getStreetId());

                    }

                }


            }
            // 出证点
            organization1.setOrgType(OrgTypeEnum.OrgType_cert.getCode());
            List<Organization> cert = organizationService.select(organization1);
            List<SysLabelModel> certSysLabelModels = new ArrayList<>();
            for (Organization certOrg : cert) {
                SysLabelModel sysLabelModel = new SysLabelModel();
                sysLabelModel.setLabel(certOrg.getName());
                sysLabelModel.setValue(Math.toIntExact(certOrg.getId()));
                certSysLabelModels.add(sysLabelModel);
            }
            //申报点
            organization1.setOrgType(OrgTypeEnum.OrgType_declaration.getCode());
            List<Organization> declaration = organizationService.select(organization1);
            List<SysLabelModel> declarationSysLabelModels = new ArrayList<>();
            for (Organization deOrg : declaration) {
                SysLabelModel sysLabelModel = new SysLabelModel();
                sysLabelModel.setLabel(deOrg.getName());
                sysLabelModel.setValue(Math.toIntExact(deOrg.getId()));
                declarationSysLabelModels.add(sysLabelModel);
            }

            Map map = new HashMap();
            map.put("cert", certSysLabelModels);
            map.put("declaration", declarationSysLabelModels);
            return Response.ok(map);

        } else {
            throw new OPServerException("机构id不合法");
        }

    }


    /**
     * 将一个 Map 对象转化为一个 JavaBean
     *
     * @param clazz 要转化的类型
     * @param map   包含属性值的 map
     * @return 转化出来的 JavaBean 对象
     * @throws IntrospectionException    如果分析类属性失败
     * @throws IllegalAccessException    如果实例化 JavaBean 失败
     * @throws InstantiationException    如果实例化 JavaBean 失败
     * @throws InvocationTargetException 如果调用属性的 setter 方法失败
     */
    @SuppressWarnings("rawtypes")
    public static <T> T toBean(Class<T> clazz, Map map) {
        T obj = null;
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
            obj = clazz.newInstance(); // 创建 JavaBean 对象

            // 给 JavaBean 对象的属性赋值
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (int i = 0; i < propertyDescriptors.length; i++) {
                PropertyDescriptor descriptor = propertyDescriptors[i];
                String propertyName = descriptor.getName();
                if (map.containsKey(propertyName)) {
                    // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
                    Object value = map.get(propertyName);
                    if ("".equals(value)) {
                        value = null;
                    }
                    Object[] args = new Object[1];
                    args[0] = value;
                    try {
                        descriptor.getWriteMethod().invoke(obj, args);
                    } catch (InvocationTargetException e) {
                        System.out.println("字段映射失败");
                    }
                }
            }
        } catch (IllegalAccessException e) {
            System.out.println("实例化 JavaBean 失败");
        } catch (IntrospectionException e) {
            System.out.println("分析类属性失败");
        } catch (IllegalArgumentException e) {
            System.out.println("映射错误");
        } catch (InstantiationException e) {
            System.out.println("实例化 JavaBean 失败");
        }

        return (T) obj;

    }


    /**
     * 查看政府端用户 list
     *
     * @param orgId
     * @param depId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @OpenMethod(key = "boss.user.selectUserList",
            paramNames = {"areaList", "orgId", "depId", "phone", "userName", "userRole","pageNum", "pageSize"},
            httpMethods = RequestMethod.GET

    )
    public Response aa(List<Integer> areaList, Long orgId, Long depId, String phone, String userName,Integer userRole, Integer pageNum, Integer pageSize) {
        //查询区域
        PageInfo pageInfo = new PageInfo();
        Organization organization = new Organization();
        if (orgId != null) {
            if (depId == null) {
                List<OrganizationUser> organizationUserList = organizationUserService.getListByOrgId(orgId);
                List<Long> userIdList = new ArrayList<>();
                userIdList.add(-1L);
                for (OrganizationUser organizationUser : organizationUserList) {
                    userIdList.add(organizationUser.getUserId());
                }
                pageInfo = mzUserService.selectByUserIdList(userIdList, userName, phone,userRole, pageNum, pageSize);

            } else {
                List<OrganizationUser> organizationUserList = organizationUserService.getListByOrgId(depId);
                List<Long> userIdList = new ArrayList<>();
                userIdList.add(-1L);
                for (OrganizationUser organizationUser : organizationUserList) {
                    userIdList.add(organizationUser.getUserId());
                }
                pageInfo = mzUserService.selectByUserIdList(userIdList, userName, phone,userRole, pageNum, pageSize);
            }

        } else {
            switch (areaList.size()) {

                case 1:
                    organization.setProvinceId(areaList.get(0));
                    break;
                case 2:
                    organization.setProvinceId(areaList.get(0));
                    organization.setCityId(areaList.get(1));
                    break;
                case 3:
                    organization.setProvinceId(areaList.get(0));
                    organization.setCityId(areaList.get(1));
                    organization.setRegionId(2);
                    break;
                case 4:
                    organization.setProvinceId(areaList.get(0));
                    organization.setCityId(areaList.get(1));
                    organization.setRegionId(areaList.get(2));
                    organization.setStreetId(areaList.get(3));
                    break;

            }
            organization.setOrgType(OrgTypeEnum.OrgType_organization.getCode());
            List<Organization> organizationList = organizationService.select(organization);
            // 查询多个单位

            List<Long> longList = new ArrayList<>();//单位List
            longList.add(-1L);
            for (Organization organization1 : organizationList) {
                longList.add(organization1.getId());
            }
            pageInfo = mzUserService.selectByUserIdList(organizationUserService.userIdList(longList), userName, phone, userRole,pageNum, pageSize);
        }

        return Response.ok(pageInfo);
    }

    /**
     * 查看 养殖人员 或者屠宰人员
     *
     * @param areaList
     * @param phone
     * @param userName
     * @param farmId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @OpenMethod(key = "boss.user.selectUserFarmList",
            paramNames = {"areaList", "phone", "userName", "farmId", "farmType", "userRole","pageNum", "pageSize"},
            httpMethods = RequestMethod.GET

    )
    public Response aa(List<Integer> areaList, String phone, String userName, Long farmId, Integer farmType,Integer userRole, Integer pageNum, Integer pageSize) {
        PageInfo pageInfo = new PageInfo();
        Map farmMap = new HashMap();
        List<FarmsDto> farmsDtos = new ArrayList<>();
        Integer areaSize = areaList.size();
        switch (areaSize) {
            case 1:
                farmMap.put("provinceId", areaList.get(0));
                break;
            case 2:
                farmMap.put("provinceId", areaList.get(0));
                farmMap.put("cityId", areaList.get(1));
                break;
            case 3:
                farmMap.put("provinceId", areaList.get(0));
                farmMap.put("cityId", areaList.get(1));
                farmMap.put("regionId", areaList.get(2));

                break;
            case 4:
                farmMap.put("provinceId", areaList.get(0));
                farmMap.put("cityId", areaList.get(1));
                farmMap.put("regionId", areaList.get(2));
                farmMap.put("streetId", areaList.get(3));

                break;
            case 5:
                farmMap.put("provinceId", areaList.get(0));
                farmMap.put("cityId", areaList.get(1));
                farmMap.put("regionId", areaList.get(2));
                farmMap.put("streetId", areaList.get(3));
                farmMap.put("villageId", areaList.get(4));
                break;
            default:
                break;

        }
        farmMap.put("farmType", farmType);
        if (farmId != null) {
            farmMap.put("farmId", farmId);
        }
        farmsDtos = farmsService.selectFarmStock(farmMap);


        List<Long> farmIdList = new ArrayList<>();
        farmIdList.add(-1L);
        for (FarmsDto farmsDto : farmsDtos) {
            farmIdList.add(farmsDto.getId());
        }
        List<Long> userIdList = farmsUserService.getUserIdList(farmIdList);
        pageInfo = mzUserService.selectByUserIdList(userIdList, userName, phone, userRole,pageNum, pageSize);
        return Response.ok(pageInfo);
    }


    /**
     * 根据用户id查询登录日志
     *
     * @param userId
     * @return
     */
    @OpenMethod(key = "boss.user.selectUserLoginLog",
            paramNames = {"userId", "pageNum", "pageSize"},
            httpMethods = RequestMethod.GET

    )
    public Response<PageInfo> selectUserLoginLog(Long userId, Integer pageNum, Integer pageSize) {
        if (userId == null) {
            return Response.fail(HttpCode.BAD_REQUEST, "参数不正确");
        }
        PageInfo<LogsUserLogin> logsUserLogins = logsUserLoginService.queryListByUserId(userId, pageNum, pageSize);
        return Response.ok(logsUserLogins);
    }

    /**
     * 根据用户id查询负责区域
     *
     * @param userId
     * @return
     */
    @OpenMethod(key = "boss.area.GovUserAreaByUserId",
            paramNames = {"userId"},
            httpMethods = RequestMethod.GET)
    public Response<List<Object>> queryLocationArea(Long userId) {

        List list = orgUserAreaService.queryLocationArea(userId);

        return Response.ok(list);
    }

    /**
     * 用户详情
     *
     * @param userId
     * @return
     */
    @OpenMethod(key = "boss.user.getUserInformation",
            paramNames = {"userId"},
            httpMethods = RequestMethod.GET

    )
    public Response<Map> getUserInformation(Long userId) {

        MzUser mzUser = mzUserService.getMzUser(userId);
        List<OrganizationUser> list = organizationUserService.selectByUserId(userId);
        for (OrganizationUser organizationUser : list) {
            switch (organizationUser.getType()) {
                case 1:
                    String orgName = organizationService.getOrganizationById(organizationUser.getOrgId()).getName();
                    mzUser.setOrgName(orgName);
                    break;
                case 2:
                    String depName = organizationService.getOrganizationById(organizationUser.getOrgId()).getName();
                    mzUser.setDepName(depName);
                    break;
            }
        }
        List<RoleAppUser> roleAppUsers = roleAppUserService.queryRoleAppByUserId(userId);
        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(userId);
        LoginUser loginUser1 = ssoLoginService.selectOne(loginUser);

        Farms farms = farmsUserService.getFarmByUserId(userId);
        if (farms != null) {
            mzUser.setFarmName(farms.getFarmsname());
        }

        Map map = new HashMap();
        map.put("mzUser", mzUser);
        map.put("RoleAppUser", roleAppUsers);
        map.put("loginUser", loginUser1);
        return Response.ok(map);

    }

    /**
     * 更新用户登录状态
     *
     * @param userId
     * @param status
     * @return
     */
    @OpenMethod(key = "boss.user.updateUserLoginStatus",
            paramNames = {"userId", "status"},
            httpMethods = RequestMethod.POST

    )
    @Transactional
    public Response<String> updateUserLoginStatus(Long userId, Integer status) {
        if (userId == null) {
            throw new OPServerException(HttpCode.BAD_REQUEST, "参数不正确");
        }
        if (status == null) {
            throw new OPServerException(HttpCode.BAD_REQUEST, "参数不正确");
        }
        if (status == UserEnum.LOGIN_ENABLE.getCode()) {
            try {
                ssoLoginService.updateUserLoginStatus(userId, UserEnum.LOGIN_ENABLE);
                return Response.ok("禁用成功");
            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.getMessage());
                throw new OPServerException(HttpCode.DATA_UPDATE_FAIL, "禁用失败");
            }

        } else {
            try {
                ssoLoginService.updateUserLoginStatus(userId, UserEnum.LOGIN_DISABLE);
                return Response.ok("启用成功");
            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.getMessage());
                throw new OPServerException(HttpCode.DATA_UPDATE_FAIL, "启用失败请稍后再试");
            }

        }

    }

    /**
     * 更新用户密码
     *
     * @param userId
     * @param passWord
     * @return
     */
    @OpenMethod(key = "boss.user.updatePassword",
            paramNames = {"userId", "passWord"},
            httpMethods = RequestMethod.POST

    )
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class, RuntimeException.class})
    public Response<String> updatePassword(Long userId, String passWord) {
        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(userId);
        LoginUser loginUserNew = ssoLoginService.selectOne(loginUser);
        loginUserNew.setPassword(MD5Util.encrypt(loginUserNew.getSalt() + passWord));
        try {
            ssoLoginService.updateByPrimaryKeySelective(loginUserNew);
            return Response.ok("密码更新成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return Response.fail(HttpCode.DATA_UPDATE_FAIL, "密码更新失败");
        }
    }

    /**
     * 查询手机号
     *
     * @param phone
     * @return
     */
    @OpenMethod(key = "boss.Phone.check",
            paramNames = {"phone"},
            httpMethods = RequestMethod.GET)
    public Response<String> phoneCheck(String phone) {
        MzUser mzUser = new MzUser();
        mzUser.setMobile(phone);
        MzUser mzUser1 = mzUserService.selectOne(mzUser);
        if (mzUser1 == null) {
            return Response.ok("此手机号可以使用");
        } else {
            return Response.fail("此手机号已经注册过");
        }
    }


}